﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////

// Reviewed

#pragma once
#include "GcmpModelInterface.h"
#include <set>

namespace gcmp
{
    class ElementId;

    /// \brief 报告引用的Element的id为拷贝、保持、放弃
    ///
    /// 假设Element A引用了Element B的id，只拷贝A得到A'，则当B
    /// 1. 报告为拷贝：拷贝B得到B'，A'中引用的B的Id替换成B'的Id。
    /// 2. 报告为保持：不拷贝B，A'中引用的B的ElementId不变。
    /// 3. 报告为放弃：不拷贝B，为放弃引用的A'中的B的id，将B的id作为参数，调用A'的UpdateForWeakParentDeletion方法。
    class GCMP_MODEL_INTERFACE_EXPORT ICopyStrategyReporter
    {
    public:
        /// \brief 创建空的拷贝策略报告器
        /// \return 返回创建出的拷贝策略报告器
        static OwnerPtr<ICopyStrategyReporter> Create();

        /// \brief 报告为拷贝
        /// \param elementId Element的Id
        /// \return void
        virtual void ReportToCopy(const ElementId & elementId) = 0;

        /// \brief 报告为保持
        /// \param elementId Element的Id
        /// \return void
        virtual void ReportToKeep(const ElementId & elementId) = 0;

        /// \brief 报告为放弃
        /// \param elementId Element的Id
        /// \return void
        virtual void ReportToDiscard(const ElementId & elementId) = 0;

        /// \brief 获取所有报告为拷贝的Elements的Id
        /// \return const std::set<gcmp::ElementId>&
        virtual const std::set<gcmp::ElementId>& GetIdsToCopy(void) const = 0;

        /// \brief 获取所有报告为保持的Elements的Id
        /// \return const std::set<gcmp::ElementId>&
        virtual const std::set<gcmp::ElementId>& GetIdsToKeep(void) const = 0;

        /// \brief 获取所有报告为放弃的Elements的Id
        /// \return const std::set<gcmp::ElementId>&
        virtual const std::set<gcmp::ElementId>& GetIdsToDiscard(void) const = 0;

        /// \brief 不报告为拷贝
        /// \param elementId Element的Id
        /// \return void
        virtual void DoNotReportToCopy(const ElementId & elementId) = 0;

        /// \brief 不报告为保持
        /// \param elementId Element的Id
        /// \return void
        virtual void DoNotReportToKeep(const ElementId & elementId) = 0;

        /// \brief 不报告为放弃
        /// \param elementId Element的Id
        /// \return void
        virtual void DoNotReportToDiscard(const ElementId & elementId) = 0;

    public:
        /// \brief 析构函数
        virtual ~ICopyStrategyReporter() = 0;
    };

    /// \brief 提供模板方法帮助批量报告引用的Elements的Id为拷贝、保持、放弃
    class ICopyStrategyReporterUtils
    {
    public:
        template<typename ForwardIterator>
        inline static void ReportToCopy(ICopyStrategyReporter & copyStrategyReporter, ForwardIterator First, ForwardIterator Last)
        {
            for (; First != Last; ++First)
            {
                copyStrategyReporter.ReportToCopy(*First);
            }
        }

        template<typename ForwardIterator>
        inline static void ReportToKeep(ICopyStrategyReporter & copyStrategyReporter, ForwardIterator First, ForwardIterator Last)
        {
            for (; First != Last; ++First)
            {
                copyStrategyReporter.ReportToKeep(*First);
            }
        }

        template<typename ForwardIterator>
        inline static void ReportToDiscard(ICopyStrategyReporter & copyStrategyReporter, ForwardIterator First, ForwardIterator Last)
        {
            for (; First != Last; ++First)
            {
                copyStrategyReporter.ReportToDiscard(*First);
            }
        }
    };
};


